package com.xxxtea.component;

import com.alibaba.excel.exception.ExcelDataConvertException;
import com.xxxtea.common.Result;
import com.xxxtea.common.UserContext;
import com.xxxtea.common.execption.BusinessException;
import com.xxxtea.common.execption.NoAuthException;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.stream.Collectors;

/**
 * 全局异常处理器
 * 
 * 统一处理系统中的各种异常，保证接口返回结构一致，便于前端处理。
 * 支持业务异常、权限异常、参数校验异常、数据库异常、Excel导入异常等。
 * 日志记录详细异常信息，便于排查问题。
 * 
 * @author badman
 * @since 1.0.0
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

	/**
	 * 处理无权限异常
	 * 
	 * @param e 无权限异常
	 * @return 统一错误响应
	 */
	@ExceptionHandler(NoAuthException.class)
	public Result<String> handleNoAuthException(NoAuthException e) {
		log.error("令牌过期或无效", e);
		return Result.error(HttpStatus.UNAUTHORIZED.value(), e.getMessage());
	}

	/**
	 * 处理参数校验异常
	 * 
	 * @param e 参数校验异常
	 * @return 统一错误响应
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public Result<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
		String errorMsg = e.getBindingResult().getAllErrors().stream()
				.map(DefaultMessageSourceResolvable::getDefaultMessage)
				.collect(Collectors.joining(";"));
		return Result.error(errorMsg);
	}

	/**
	 * 处理业务异常
	 * 
	 * @param e 业务异常
	 * @return 统一错误响应
	 */
	@ExceptionHandler(BusinessException.class)
	public Result<String> handleBusinessException(BusinessException e) {
		log.error("业务异常", e);
		return Result.error(e.getMessage());
	}

	/**
	 * 处理Excel导入异常
	 * 
	 * @param e Excel数据转换异常
	 * @return 统一错误响应
	 */
	@ExceptionHandler(ExcelDataConvertException.class)
	public Result<String> handleExcelDataConvertException(ExcelDataConvertException e) {
		log.error("Excel异常", e);
		return Result.error("Excel导入失败");
	}

	/**
	 * 处理数据库持久化异常
	 * 
	 * @param e 数据库异常
	 * @return 统一错误响应
	 */
	@ExceptionHandler(PersistenceException.class)
	public Result<String> handlePersistenceException(PersistenceException e) {
		log.error("操作数据库异常", e);
		return Result.error("操作数据库异常");
	}

	/**
	 * 处理非法请求异常
	 * 
	 * @param e 消息不可读异常
	 * @return 统一错误响应
	 */
	@ExceptionHandler(HttpMessageNotReadableException.class)
	public Result<String> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
		log.error("非法请求! userId: " + UserContext.getId(), e);
		return Result.error("非法请求");
	}

	/**
	 * 处理所有未捕获的异常
	 * 
	 * @param e 未知异常
	 * @return 统一错误响应
	 */
	@ExceptionHandler(Exception.class)
	public Result<String> handleException(Exception e) {
		log.error(e.getMessage(), e);
		return Result.error("服务器异常");
	}
}
